#!/usr/bin/env python
# _*_coding:utf-8_*_

"""
@Time :    2019/9/22 18:40
@Author:  ThinHeader
@File: tasks.py
@Software: PyCharm
"""
import json
import logging
from datetime import timedelta

from django.utils import timezone

from common.views import get_obj
from common.wx.WXBizMsgCrypt import WxCryptConfig
from common.wx.lib import WeixinHelper
from open.models import ComponentTicket, WxPublicInfo, ComponentAccessToken, WxPublicAccess, PreAuthCode, \
    WxPublicMapShop
from qixiaobao.celery import app

logger = logging.getLogger('qixiaobao')


def get_component_access_token():
    """获得开放平台access token"""
    ticket = ComponentTicket.objects.filter(status=ComponentTicket.STATUS_VALID).first().ticket
    data = json.loads(WeixinHelper.getComponentAccessToken(WxCryptConfig.app_id, WxCryptConfig.app_secret, ticket))
    token = data['component_access_token']
    expires = data['expires_in']
    return token, expires


def get_pre_auth_code():
    """获得预授权码"""
    token = ComponentAccessToken.objects.filter(status=ComponentAccessToken.STATUS_VALID).first().token
    data = json.loads(WeixinHelper.getPreAuthCode(WxCryptConfig.app_id, token))
    if 'pre_auth_code' not in data:
        logger.debug('get_pre_auth_code(pre_auth_code) : %s' % data)
    return data['pre_auth_code'], data['expires_in']


def update_public_token(app_id):
    """刷新微信公众号token"""
    try:
        wpa = WxPublicAccess.objects.get(app_id=app_id, status=WxPublicAccess.STATUS_VALID)
    except WxPublicAccess.DoesNotExist:
        return False

    data = json.loads(WeixinHelper.getAuthorizerToken(wpa.access_token, WxCryptConfig.app_id,
                                                      wpa.app_id, wpa.refresh_token))
    authorizer_access_token = data['authorizer_access_token']
    expires_in = data['expires_in']
    authorizer_refresh_token = data['authorizer_refresh_token']
    wpa.access_token = authorizer_access_token
    wpa.expires = expires_in
    wpa.refresh_token = authorizer_refresh_token
    wpa.save()


def update_public_info(app_id):
    """获得微信公众号信息"""
    # 刷新信息
    token = ComponentAccessToken.objects.all().first().token
    data = json.loads(WeixinHelper.getAuthInfo(WxCryptConfig.app_id, app_id, token))
    logger.debug('update_public_info(getAuthInfo) : %s' % data)
    info = data['authorizer_info']
    nick_name = info['nick_name']
    if 'head_img' in data:
        head_img = info['head_img']
    else:
        head_img = ''
    service_type_info = info['service_type_info']['id']
    verify_type_info = info['verify_type_info']['id']
    user_name = info['user_name']
    business_info = ','.join([str(info['business_info']['open_store']), str(info['business_info']['open_scan']),
                              str(info['business_info']['open_pay']), str(info['business_info']['open_card']),
                              str(info['business_info']['open_shake'])])
    if 'alias' in info:
        alias = info['alias']
    else:
        alias = ''
    qrcode_url = info['qrcode_url']
    auth_info = data['authorization_info']
    app_id = auth_info['authorizer_appid']
    id_list = []
    for func in auth_info['func_info']:
        id_list.append(str(func['funcscope_category']['id']))
    func_info = ','.join(id_list)

    if 'MiniProgramInfo' in info:
        wx_type = WxPublicInfo.WX_XCX
    else:
        wx_type = WxPublicInfo.WX_PUBLISH

    wpi = get_obj(WxPublicInfo, app_id=app_id, status=WxPublicInfo.STATUS_VALID)
    if wpi:
        wpi.nick_name = nick_name
        wpi.head_img = head_img
        wpi.service_type_info = service_type_info
        wpi.verify_type_info = verify_type_info
        wpi.user_name = user_name
        wpi.alias = alias
        wpi.business_info = business_info
        wpi.qrcode_url = qrcode_url
        wpi.func_info = func_info
        wpi.wx_type = wx_type
        wpi.save()
    else:
        WxPublicInfo.objects.create(app_id=app_id,
                                    nick_name=nick_name,
                                    head_img=head_img,
                                    service_type_info=service_type_info,
                                    verify_type_info=verify_type_info,
                                    user_name=user_name,
                                    alias=alias,
                                    business_info=business_info,
                                    qrcode_url=qrcode_url,
                                    func_info=func_info,
                                    wx_type=wx_type,
                                    status=WxPublicInfo.STATUS_VALID)
    return wx_type


@app.task()
def component_access_token_task():
    """刷新开放平台component_access_token"""
    cat = ComponentAccessToken.objects.first()
    if not cat:
        token, expires = get_component_access_token()
        ComponentAccessToken.objects.create(token=token, expires=expires, status=ComponentAccessToken.STATUS_VALID)
    elif (cat.expires <= 1800) or (cat.last_mod_time + timedelta(seconds=5400) < timezone.now()):
        token, expires = get_component_access_token()
        cat.token = token
        cat.expires = expires
        cat.save()
        return token
    else:
        cat.expires -= 900
        cat.save()
    return cat.expires


@app.task()
def pre_auth_code_task():
    """刷新预授权码"""
    cat = PreAuthCode.objects.first()
    if not cat:
        code, expires = get_pre_auth_code()
        PreAuthCode.objects.create(code=code, expires=expires, status=PreAuthCode.STATUS_VALID)
    elif cat.expires <= 600:
        code, expires = get_pre_auth_code()
        cat.code = code
        cat.expires = expires
        cat.save()
        return code, expires
    else:
        cat.expires -= 300
        cat.save()

    return cat.expires


@app.task()
def public_access_token_task():
    """刷新微信公众号token"""
    token = ComponentAccessToken.objects.first().token
    publish_list = WxPublicMapShop.objects.filter(status=WxPublicMapShop.STATUS_VALID).values('app_id')
    xcx_list = WxPublicMapShop.objects.filter(status=WxPublicMapShop.STATUS_VALID).values('xcx_id')
    publish_set = set([item['app_id'] for item in publish_list])
    xcx_set = set([item['xcx_id'] for item in xcx_list])
    publish_set = publish_set | xcx_set
    now = timezone.now()

    for app_id in publish_set:
        if not app_id:
            continue
        wpa = get_obj(WxPublicAccess, app_id=app_id, status=WxPublicAccess.STATUS_VALID)
        if not wpa:
            logger.debug('PublicAccessTokenTask:WXPublicAccess not exist:%s' % app_id)
            continue

        if (wpa.expires > 1800) and (wpa.last_mod_time + timedelta(seconds=5400) > now):
            wpa.expires -= 900
        else:
            # 刷新token
            data = json.loads(WeixinHelper.getAuthorizerToken(token, WxCryptConfig.app_id,
                                                              wpa.app_id, wpa.refresh_token))
            if 'authorizer_access_token' in data:
                authorizer_access_token = data['authorizer_access_token']
                expires_in = data['expires_in']
                authorizer_refresh_token = data['authorizer_refresh_token']
                wpa.access_token = authorizer_access_token
                wpa.expires = expires_in
                wpa.refresh_token = authorizer_refresh_token
                wpa.save()
            else:
                logger.debug('refresh public token error:%s' % data)
        if wpa.expires_ticket > 1800:
            wpa.expires_ticket -= 900
        else:
            # 刷新ticket
            data_ticket = json.loads(WeixinHelper.getJsapiTicket(wpa.access_token))
            if 'ticket' in data_ticket:
                wpa.ticket = data_ticket['ticket']
                wpa.expires_ticket = data_ticket['expires_in']
        wpa.save()

    return 'success'
